﻿using QntPlatform.Strategy.CmdCtrl;
using System;
using System.Linq;

namespace QntPlatform.Strategy.S2
{
    [ArgInfo(Remark = @"普通信号;
接收[止盈1,方向]，执行：仓位、止损，1/2止盈、保本止损、1/2追踪止盈
请求内容格式：{""Period"":60,""islong"":true,""sells"":[1000]}"
)]
    public class PuTong:PeriodTrandBase<PuTong.TradeCmd>
    {
        [ArgInfo(Remark = "可承受止损率,用于仓位计算")]
        decimal stopLossRatio { get; set; } = 0.02m;
         [ArgInfo(Remark = "跟踪止盈回撤率")]
        public decimal StopProfitForSlideRate { get; set; }=0.01m;
        public override void Execute(TradeCmd cmdVal)
        {
            var ret = Exchange.GetRecordsAsync(cmdVal.Period.Value);
            var account = Exchange.GetAccountAsync();
            var tck = Exchange.GetTickerAsync();
            //计算止损：数量，止损价，止损类型(固定）
            decimal stopLoss = StopLossCalc(ret.Result, cmdVal.IsLong.Value);
            //交易：仓位计算
            var nowPrice = tck.Result.Buy;
            decimal buyAmount = AmountCalc(account.Result, stopLoss, nowPrice, cmdVal.IsLong.Value);
            if (buyAmount <= 0)
            {
                Log.Warn("仓位无效，空执行处理", new { account.Result, stopLoss, nowPrice, cmdVal });
                return;
            }
            var id = Exchange.CreateOrder(buyAmount, DirectionTo.InFor(cmdVal.IsLong));//   Exchange.BuyAsync(buyAmount) : Exchange.SellAsync(-1, buyAmount);  // execTrade(DirectionTo.InFor(cmdVal.IsLong), buyAmount);
            //计算止盈：数量，止盈价，止盈类型(跟踪、固定)，止盈后动作(设置止损)

            var spl = new StopLoss(this, new StopLoss.StopLossInfo() { Amount = buyAmount, StopLossPrice = stopLoss, IsCloseBuy = cmdVal.IsLong.Value, Info = GetHashCode() });
            var profitPrice = BiaoZhun.calcProfitSlideDownPrice(nowPrice, cmdVal.sells[0], BiaoZhun.profitSlideDownRate, cmdVal.IsLong.Value);
            Log.Debug("计算滑动0.85后止盈",profitPrice);
            var fp = new TrailingStep2.FixedProfit(this) { Amount = Exchange.getAmount(buyAmount / 2), Price = profitPrice, IsLong = cmdVal.IsLong.Value, Sid = "" + GetHashCode() };
            fp.AfterFun = () => spl.Data.StopLossPrice = nowPrice;
            var tp = new TrailingProfit(this, new TrailingProfit.TrailingProfitData() { Sid = GetHashCode() + "", Amount = buyAmount - Exchange.getAmount(buyAmount / 2), InPrice = nowPrice, CloseDirection = DirectionTo.CloseFor(cmdVal.IsLong) });
            tp.SetProfitRate(profitPrice);
            tp.profitSlideRate=StopProfitForSlideRate;
            //
            new TuPo_2.TuPo2TaskItem(this) { stopLoss1 = spl, fixedProfit = fp, trailingProfit = tp, sourcePrice = nowPrice, Exchange = Exchange }.Init();
            return;
        }

        private decimal AmountCalc(Account account, decimal stopLoss, decimal nowPrice, bool isLong)
        {
            var longVal = isLong ? 1 : -1;
            var bl = account.Balance;
            if (Exchange is BinanceApi.DApi.USDExchangeImp)
            {
                bl = nowPrice * bl;
            }
            var am = longVal * bl * stopLossRatio / (nowPrice - stopLoss);
            return Exchange.getAmount(am);
        }

        private decimal StopLossCalc(Record[] records, bool isLong)
        {
            var last7 = records.Skip(records.Length - 7); // Aggregate((p1, p2) =>(p1 == null || p1.Low > p2.Low)?p2:p1);
            var top = isLong ? last7.Min(p => p.Low) : last7.Max(p => p.High);
            var atr = (decimal)TA.ATR(records, 14).Last();
            var atrV = isLong ? -atr * 0.5m : atr * 0.5m;
            var stopLoss = top + atrV; //止损价
            Log.Debug("止损计算信息", new { stopLoss, top, atr });
            return stopLoss;
        }

 

        public class TradeCmd:TradeInfo
        {
            /// <summary>
            /// 止盈点
            /// </summary>
            public decimal[] sells { get; set; }
 
        }
     
    }
}
